package controlisolation.lifecyclefsm.controlcodegenerator;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SCXMLParser extends DefaultHandler {

    private boolean bscxml = false;
    private boolean bstate = false;
    private boolean btransition = false;
    
   
    private Map<String,String> _currentStateAttributesMap; 
    private List<Map<String,String>> _currentStateTransitionsAttributesMap;
    
    private SAXParserFactory _factory;
    private SAXParser _saxParser;
    private List<SCXMLParserListener> _listeners;

    public SCXMLParser() {
        _listeners = new ArrayList();
    }

    public boolean init() {
        try {
            _factory = SAXParserFactory.newInstance();
            _saxParser = _factory.newSAXParser();
            
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    public boolean parse(String fileName) {
        try {
            _saxParser.parse(new File(fileName), this);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    private void attributesToMap(Map<String,String> map,Attributes attrs)
    {
               
        for (int i=0;i<attrs.getLength();i++)
        {
            String name=attrs.getQName(i);
            String value=attrs.getValue(i);
            map.put(name,value);
        }
    }
    
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {

        //System.out.println("Start Element :" + qName);

        if (qName.equalsIgnoreCase("SCXML")) {
            bscxml = true;
        }

        if (qName.equalsIgnoreCase("STATE")) {
            _currentStateAttributesMap=new HashMap<String,String>();
            attributesToMap(_currentStateAttributesMap,attributes);
            //System.out.println(_currentStateAttributesMap.get("id")+" state found");
            _currentStateTransitionsAttributesMap=new ArrayList<Map<String,String>>();
            notifyStateStart(_currentStateAttributesMap);
            bstate = true;
        }

        if (qName.equalsIgnoreCase("TRANSITION")) {
            Map<String,String> attributesmap=new HashMap<String,String>();
            attributesToMap(attributesmap,attributes);
            _currentStateTransitionsAttributesMap.add(attributesmap);
            
        }

    }

    @Override
    public void endElement(String uri, String localName,
            String qName) throws SAXException {

        //System.out.println("End Element :" + qName);
        //System.out.println("bstate="+bstate+" btransition="+btransition);
        if (qName.equalsIgnoreCase("STATE"))
        {
         bstate = false;
         notifyStateEnd(_currentStateTransitionsAttributesMap);
            //System.out.println(_currentStateAttributesMap.get("id")+" Has "+_currentStateTransitionsAttributesMap.size()+" transitions.");
        } else
        if (qName.equalsIgnoreCase("TRANSITION"))
        {
            btransition = false; 
        }
        
    }

    @Override
    public void characters(char ch[], int start, int length) throws SAXException {

        if (bscxml) {
            //System.out.println("SCXML : " + new String(ch, start, length));
            bscxml = false;
        }

        if (bstate) {
            //System.out.println("STATE : " + new String(ch, start, length));
            bstate=false;
        }

        if (btransition) {
            //System.out.println("TRANSITION : " + new String(ch, start, length));
            btransition = false;
        }

    }

    public void addListener(SCXMLParserListener val) {
        _listeners.add(val);
    }

    
    private void notifyStateStart(Map<String,String> attributesmap) {
        for (SCXMLParserListener listener : _listeners) {
            listener.stateStart(attributesmap);
        }
    }
    
    private void notifyStateEnd(List<Map<String,String>> transitions_attributes) {
        for (SCXMLParserListener listener : _listeners) {
            listener.stateEnd(transitions_attributes);
        }
    }

    
    
}